<!DOCTYPE html>
<html lang="en">
  <head>
        <!-- 引入 echarts.js -->
        <script src="http://pic.beeboom.net/sourse/echarts.min.js"></script>
        <!-- 引入主题 -->
        <script src="http://pic.beeboom.net/sourse/wonderland.js"></script>

      <!-- vue -->
      <script src="http://pic.beeboom.net/sourse/vue.min.js"></script>
        
      <!-- element-ui css-->
      <link rel="stylesheet" href="http://pic.beeboom.net/sourse/element-ui@2.15.7/lib/theme-chalk/index.min.css">

        <!-- 引入axios -->
        <script src="http://pic.beeboom.net/sourse/axios_0.26.0_axios.min.js"></script>
        <!-- element-ui js-->
        <script src="http://pic.beeboom.net/sourse/element-ui@2.15.7_lib_index.min.js"></script>
        <!-- 引入mqtt.js -->
        <script src="http://pic.beeboom.net/sourse/mqtt.min.js"></script>
          <!-- 引入xlsx -->
          <!-- <script src="http://pic.beeboom.net/sourse/xlsx.full.min.js"></script> -->
          <!-- <script src="http://pic.beeboom.net/sourse/FileSaver.js"></script> -->
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <!-- <meta http-equiv="refresh" content="120"> -->
      <meta name="viewport" content="width=device-width, initial-scale=1.0,  minimum-scale=0.5, maximum-scale=2.0, user-scalable=yes"/>
      <title>mqtt调试页面</title>

  </head>
  <body>   
      <div id="app"> 
        <el-container>
          <el-header>
            <h2>MQTT调试工具</h2>
          </el-header>
          <el-main>
            <div>
              <label>服务器地址:</label>
              <el-input v-model="serverUrl" placeholder="www.hzne.cloud" style="margin: 5px 0; width: 400px;"></el-input>
            </div>
            <div>
              <label>端口:</label>
              <el-input-number v-model="port" :min="1" :max="65535" style="margin: 5px 0; width: 400px;" :disabled="true"></el-input-number>
            </div>
            <div>
              <label>Client ID:</label>
              <el-input v-model="clientId" readonly style="margin: 5px 0; width: 400px;"></el-input>
            </div>
            <div>
              <label>用户名:</label>
              <el-input v-model="username" style="margin: 5px 0; width: 400px;"></el-input>
            </div>
            <div>
              <label>密码:</label>
              <el-input v-model="password" type="password" style="margin: 5px 0; width: 400px;"></el-input>
            </div>
            <div>
              <el-button type="primary" @click="connectMQTT" :disabled="isConnecting">连接</el-button>
              <el-button type="danger" @click="disconnectMQTT">断开</el-button>
              <span :style="{ color: isConnected ? 'green' : 'red' }" style="margin-left: 10px;">
                ● {{ isConnected ? '已连接' : '已断开' }}
              </span>
            </div>

            <el-divider></el-divider>

            <h3>订阅</h3>
            <div>
              <label>Topic:</label>
              <el-input v-model="subscribeTopic" style="margin: 5px 0; width: 400px;"></el-input>
              <el-button @click="subscribe">订阅</el-button>
            </div>
            <div>
              <label>接收到的信息:</label>
              <el-input type="textarea" v-model="receivedMessagesDisplay" rows="10" readonly style="margin: 5px 0; width: 400px;"></el-input>
            </div>
            <div>
              <label>消息格式:</label>
              <el-select v-model="messageFormat" placeholder="选择格式" style="margin: 5px 0; width: 400px;">
                <el-option label="字符串" value="string"></el-option>
                <el-option label="十六进制" value="hex"></el-option>
              </el-select>
            </div>

            <el-divider></el-divider>

            <h3>发布</h3>
            <div>
              <label>Topic:</label>
              <el-input v-model="publishTopic" style="margin: 5px 0; width: 400px;"></el-input>
            </div>
            <div>
              <label>消息:</label>
              <el-input v-model="publishMessage" style="margin: 5px 0; width: 400px;"></el-input>
            </div>
            <div>
              <label>发布消息格式:</label>
              <el-select v-model="publishMessageFormat" placeholder="选择格式" style="margin: 5px 0; width: 400px;">
                <el-option label="字符串" value="string"></el-option>
                <el-option label="十六进制" value="hex"></el-option>
              </el-select>
              <el-button @click="publish">发布</el-button>
            </div>
            <div>
              <label>发布记录:</label>
              <el-input type="textarea" v-model="publishedMessagesDisplay" rows="10" readonly style="margin: 5px 0; width: 400px;"></el-input>
            </div>
          </el-main>
        </el-container>
      </div>
  </body>
</html>

<script>
const vm = new Vue({
    el: '#app', 
    data() {
      return {
        serverUrl: 'www.hzne.cloud',
        port: 8083,
        clientId: 'hztest' + Math.random().toString(36).substring(2, 15),
        username: 'admin',
        password: 'hertz',
        subscribeTopic: '/TEST/#',
        publishTopic: '',
        publishMessage: '',
        mqttClient: null,
        receivedMessages: [],
        publishedMessages: [],
        receivedMessagesDisplay: '',
        publishedMessagesDisplay: '',
        isConnected: false,
        isConnecting: false,
        messageFormat: 'hex',
        publishMessageFormat: 'hex'
      }
    },
    mounted() {
      console.log('monitor mounted');
    },
    methods: {
      connectMQTT() {
        this.isConnecting = true;
        const options = {
          clientId: this.clientId,
          username: this.username,
          password: this.password,
          clean: true
        };

        this.mqttClient = mqtt.connect(`mqtt://${this.serverUrl}:${this.port}/mqtt`, options);

        this.mqttClient.on('connect', () => {
          console.log('Connected to MQTT broker');
          this.isConnected = true;
          this.isConnecting = false;
          this.subscribe();
        });

        this.mqttClient.on('message', (topic, message) => {
          let formattedMessage;
          console.log(message);
          console.log(message.toString());
          console.log(typeof message);
          console.log(message.length);
          if (this.messageFormat === 'hex') {
          //遍历message的每个字节，转换为十六进制,不足2位补零 
            formattedMessage = Array.from(message).map(byte => {
              return byte.toString(16).padStart(2, '0').toUpperCase();
            }).join(' ');
          } else {
            formattedMessage = message.toString();
          }
          this.receivedMessages.push(`${topic}: ${formattedMessage}`);
          this.receivedMessagesDisplay = this.receivedMessages.join('\n');
          console.log('Received message:', formattedMessage);
        });

        this.mqttClient.on('error', (error) => {
          console.error('Connection error:', error);
          this.isConnecting = false;
        });
      },
      disconnectMQTT() {
        if (this.mqttClient) {
          this.mqttClient.end();
          console.log('Disconnected from MQTT broker');
          this.isConnected = false;
        }
      },
      subscribe() {
        this.mqttClient.subscribe(this.subscribeTopic, (err) => {
          if (!err) {
            console.log(`Subscribed to topic: ${this.subscribeTopic}`);
          }
        });
      },
      publish() {
        let messageToSend;
        if (this.publishMessageFormat === 'hex') {
          // 校验十六进制格式
          if (!this.isHex(this.publishMessage)) {
            alert('请确保输入的十六进制格式正确！');
            return;
          }
          // 检查十六进制字符串的长度是否为偶数
          if (this.publishMessage.length % 2 !== 0) {
            alert('十六进制字符串必须是偶数个字符！');
            return;
          }
          // 将十六进制字符串转换为字节数组
          const byteArray = this.hexToByteArray(this.publishMessage);
          // 将字节数组转换为 Uint8Array
          messageToSend = new Uint8Array(byteArray);
        } else if (Array.isArray(this.publishMessage)) {
          // 如果发布消息是数组，转换为 JSON 字符串
          messageToSend = JSON.stringify(this.publishMessage);
        } else {
          messageToSend = this.publishMessage; // 直接使用字符串
        }

        // 保留原始格式
        this.publishedMessages.push(`${this.publishTopic}: ${this.publishMessage}`);
        this.publishedMessagesDisplay = this.publishedMessages.join('\n');

        this.mqttClient.publish(this.publishTopic, messageToSend, {}, (err) => {
          if (!err) {
            console.log(`Message published to topic: ${this.publishTopic}`);
          }
        });
      },
      hexToByteArray(hex) {
        const byteArray = [];
        for (let i = 0; i < hex.length; i += 2) {
          byteArray.push(parseInt(hex.substr(i, 2), 16)); // 将每两个字符转换为十六进制数
        }
        return byteArray; // 返回字节数组
      },
      hexToString(hex) {
        console.log(hex);
        let str = '';
        for (let i = 0; i < hex.length; i += 2) {
          str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
        }
        return str;
      },
      isHex(str) {
        return /^[0-9A-Fa-f]+$/.test(str);
      }
    }
})
</script>
<style>

</style>